<?php
/**
 * Created by PhpStorm.
 * User: steven
 * Date: 2017/9/15
 * Time: 下午2:27
 */

namespace frontend\controllers;


use common\tools\Config;
use Yii;
use yii\web\Controller;
use yii\web\Response;

class ToolsController extends Controller
{
    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        return [

        ];
    }

    public function actionIndex()
    {
        $controllerList = $this->getControllerLists();
//        print_r($controllerList);exit();
        $this->layout = 'none';
        return $this->render('index', [
            'controller_list' => $controllerList
        ]);
    }


    /**
     * @return array
     */
    public function actionDetail()
    {
        Yii::$app->response->format = Response::FORMAT_JSON;
        $request = \Yii::$app->request;
        if($request->isPost) {
            $controllerName = $request->post('controller_name');
            $whiteList = Config::get('app_white_controllers');
            if(in_array($controllerName . '.php',$whiteList)){
                return [];
            }
            $path = dirname(dirname(dirname(__FILE__))) . '/api/controllers/' . $controllerName . '.php';
            $info = $this->parsefile($path);
            return $info;
        }
    }

    /**
     * 获取所有的api接口
     * @return array
     */
    private function getControllerLists()
    {
        $whiteList = Config::get('app_white_controllers');
        $path = dirname(dirname(dirname(__FILE__))) . '/api/controllers/*.php';
        $files = glob($path);
        $pos = 0;
        $items = [];
        foreach ($files as $file) {
            $fileNameArr = explode('/', $file);
            $fileName = array_pop($fileNameArr);
            $prefix = implode('/', $fileNameArr);
            if (in_array($fileName, $whiteList)) {
                continue;
            }
            $info = $this->parsefile($prefix . '/' . $fileName);
            $pos++;
            $url = "/tools/show?info=" . urlencode(serialize($info));
            $items[] = [
                'controller' => $info['baseName'],
                'title' => $info['title'],
                'url' => $url,
                'method_info' => $info['method_info']
            ];
        }
        return $items;
    }


    private function parseFile($file)
    {
        $code = file_get_contents($file);
        if (preg_match_all('~class\s+(.+)\s+extends\s+([^\{]+)~i', $code, $matches)) {
            foreach ($matches[1] as $k => $v) {
                $name = trim($matches[1][$k]);
                $parent = trim($matches[2][$k]);
                if (substr($v, -strlen('Controller')) == 'Controller' && stristr($file, $name) !== false) {
                    $info = $this->getCodeController($file,$name,$parent);
                }
            }
        }
        return $info;
    }


    /**
     * 获取controller以及注释
     * @param $file
     * @param $name
     * @param $parent
     * @return array|bool
     */
    public function getCodeController($file,$name,$parent)
    {
        $title = substr($name, 0, -strlen('Controller'));
        $method_info = [];
        try {
            $baseName = $name;
            $name = 'api\controllers\\' . $name;
            $r = include $file;
            if ($r || is_file($r)) {
                $ref = new \ReflectionClass($name);
                $doc = $ref->getDocComment();
                if (strpos($doc, '@hide') !== false) {
                    return false;
                }
                if (preg_match('~\s+\*\s+(.+)~', $doc, $matches)) {
                    $title .= htmlspecialchars($matches[1]);
                };
                //获取method的方法
                $method_info = $this->getCodeMethod($ref);
            }
        } catch (\Exception $e) {
            \common\tools\Logger::debug('generate list error',$e->getTraceAsString());
        }
        return array(
            'file' => basename($file),
            'baseName' => $baseName,
            'title' => $title,
            'name' => $name,
            'parent' => $parent,
            'method_info' => $method_info
        );
    }


    /**
     * 获取action的传参以及注释
     * @param $ref
     * @return array
     */
    public function getCodeMethod($ref)
    {
        $method_info = [];
        $methods = $ref->getMethods();
        $code = file_get_contents($ref->getFileName());
        $code_arr = explode("\n", $code);
        foreach ($methods as $key=>$method) {
            if ('action' == substr($method->name, 0, 6)) {
                //注释
                $doc = $method->getDocComment();
                if (preg_match('~\s+\**\s+(.+)~', $doc, $matches)) {
                    $method_info[$key]['title'] = $matches['1'];
                };
                //方法名
                $method_info[$key]['name'] = $method->name;
                $method_info[$key]['start_line'] = $method->getStartLine();
                $method_info[$key]['end_line'] = $method->getEndLine();
                //action code
                $method_code = array_slice($code_arr, $method_info[$key]['start_line'],$method_info[$key]['end_line'] - $method_info[$key]['start_line']);
                foreach ($method_code as $line) {
                    $comment = explode('//', $line);
                    $comment_str = isset($comment[1]) ? $comment[1] : 1;
                    $reg2 = '~\$request\->(post|get)\(([\'\"])([^\'\"]+)(\\2).*\)~';
                    if (preg_match_all($reg2, $line, $arr)) {
                        $one_line = count($arr[1]) == 1;
                        foreach ($arr[1] as $k => $v) {
                            //参数注释以及参数key名
                            if ($v == 'post') {
                                $method_info[$key]['request']['POST'][$arr[3][$k]] = $one_line ? $comment_str : 1;

                            }else {
                                $method_info[$key]['request']['GET'][$arr[3][$k]] = $one_line ? $comment_str : 1;
                            }
                        }

                    }
                }

            }
        }
        array_pop($method_info);
        return  $method_info;
    }






}